import axios from 'axios'
import qs from 'qs' //用于将json参数请求改为表单参数请求
// import 'element-plus/es/components/message/style/css'
// import 'element-plus/es/components/message-box/style/css'
// import {ElMessage} from 'element-plus'
import {
    getRefreshTokenAtStorage,
    getTokenAtStorage,
    removeTokens,
    setRefreshTokenAtStorage,
    setTokenAtStorage
} from '@/utils/tokens.js'

// create an axios instance
const service = axios.create({
    baseURL: import.meta.env.VITE_BASE_API_URL, // api的base_url
    withCredentials: true, // send cookies when cross-domain requests
    timeout: 10000 // request timeout
})


/**GET请求，返回Promise对象*/
const get = function get(url, params) {
    return new Promise((resolve, reject) => {
        //因为get请求的参数是?a=xx
        service.get(url, {params: params})
            .then((resp) => {
                resolve(resp)
            }, (err) => {
                reject(err)
            })
    })
}

/**POST请求，form-urlencoded，返回Promise对象*/
const post_form = function post_form(url, data) {
    return new Promise((resolve, reject) => {
        //axios发送请求，返回的 responsoe:{config,data}
        service.post(url, qs.stringify(data), {headers: {'Content-Type': 'application/x-www-form-urlencoded'}})
            .then((resp) => {
                resolve(resp)
            }, (err) => {
                reject(err)
            })
    })
}

/**POST请求，Json，返回Promise对象*/
const post = function post(url, data, config) {
    return new Promise((resolve, reject) => {
        //axios发送请求，返回的 responsoe:{config,data}
        service.post(url, data, config)
            .then((resp) => {
                resolve(resp)
            }, (err) => {
                reject(err)
            })
    })
}

/**PUT请求，Json，返回Promise对象*/
const put = function put(url, data) {
    return new Promise((resolve, reject) => {
        service.put(url, data)
            .then((resp) => {
                resolve(resp)
            }, (err) => {
                reject(err)
            })
    })
}

/**DELETE请求，返回Promise对象*/
const delet = function delet(url) {
    return new Promise((resolve, reject) => {
        service.delete(url)
            .then((resp) => {
                resolve(resp)
            }, (err) => {
                reject(err)
            })
    })
}


//要携带oauth client的名单
const oauthClientList = ["/oauth2/token"]

//白名单
const whitelist = [
    "/oauth2/token", "/login", "/register", "/isOccupy",
    "/category/list", "/poster/", "/popular", "/suggest", "/search", "/p",
]


/* 睡眠函数*/
function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

/**
 * 请求拦截
 */
service.interceptors.request.use(config => {
        // do something before request is sent
        if (config.url.indexOf("undefined") !== -1) {
            throw new Error("请求url中不能含有undefined")
        }

        if (oauthClientList.some(e => config.url.startsWith(e))) {
            //携带oauth client信息
            config.headers['Authorization'] = "Basic " + window.btoa("mall:mall-my")
        }

        if (whitelist.some(e => config.url.startsWith(e))) {
            console.debug("easy access ..")
        } else {
            //携带token
            const token = getTokenAtStorage()
            if (token) {
                config.headers['Authorization'] = "Bearer " + token
            }
        }

        config.headers['X-user-type'] = "member"
        config.headers['X-uuid'] = sessionStorage.getItem('X-uuid') ?? ''

        return config
    },
    error => {
        // do something with request error
        console.log(error) // for debug
        return Promise.reject(error)
    }
)







/**
 * 响应拦截器
 */
service.interceptors.response.use(response => {
        const res = response.data

        if (res.ok !== undefined && res.ok === false) {
            console.error(res.msg || 'Error')

            return Promise.reject()
        } else {
            return res
        }
    }, err => {
        let config = err.response.config;
        if (!config.retryCount) config.retryCount = 0;

        // console.debug("response.config = "+JSON.stringify(config))
        // console.debug("response.data = "+JSON.stringify(err.response.data))
        // console.debug("url = "+config.url)
        let isRefresh = err.response.data.action === "Refresh"

        if (err.message.includes("401")) {
            //token刷新
            if (isRefresh && config.retryCount===0) {
                config.retryCount++;

                return refreshToken()
                    .then(() => {
                        // console.debug("重试请求url：url="+config.url+", retryCount="+config.retryCount);
                        //携带token
                        config.headers['Authorization'] = "Bearer " + getTokenAtStorage()
                        return service(config)
                    });
            }

            console.warn("登录认证失败：" + err.message);
            removeTokens()
            return Promise.resolve()
        }

        console.error(err.message)

        if (err.response.data) {
            console.error(err.response.data.msg)
        } else {
            console.error(err.message)
        }
        return Promise.reject(err)
    }
)

/** 刷新token */
async function refreshToken() {
    console.info("token expired, to refresh token ..", new Date());
    // console.debug("old refresh_token = "+refresh_token)
    const resp = await service.post("/auth/refresh", {refresh_token: getRefreshTokenAtStorage()})

    // console.debug(">>> refresh token data = "+JSON.stringify(resp))
    //存储token
    const token = resp.access_token
    const refreshToken = resp.refresh_token

    setTokenAtStorage(token)
    setRefreshTokenAtStorage(refreshToken)
    return resp
}

export default {
    get,
    post,
    post_form,
    put,
    delet
}
